package com.uuah.server.config.spring.parsers.assembly;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * This is used internally by
 * {@link com.uuah.server.config.spring.parsers.assembly.BeanAssembler} along
 * with
 * {@link com.uuah.server.config.spring.parsers.collection.ChildSingletonMapDefinitionParser}
 * . It creates a map with a single key/value pair. This may seem odd, but the
 * result is not manipulated within the assembler - that means that, unlike
 * {@link com.uuah.server.config.spring.parsers.collection.ChildMapEntryDefinitionParser}
 * , this element can contain nested values. Note that most uses will set
 * {@link com.uuah.server.config.spring.parsers.assembly.configuration.IPropertyConfiguration#isCollection(String)}
 * so that several entries can be combined.
 */
public class MapEntryCombiner implements Map {

	public static final String KEY = "key";
	public static final String VALUE = "value";

	private Object key;
	private Object value;
	private Map cachedMerge = new HashMap();
	private boolean isMerged = false;

	private synchronized Map getCachedMerge() {
		if (!isMerged) {
			cachedMerge.put(key, value);
			isMerged = true;
		}
		return cachedMerge;
	}

	public Object getKey() {
		assertNotMerged();
		return key;
	}

	public void setKey(Object key) {
		assertNotMerged();
		this.key = key;
	}

	public Object getValue() {
		assertNotMerged();
		return value;
	}

	public void setValue(Object value) {
		assertNotMerged();
		this.value = value;
	}

	private synchronized void assertNotMerged() {
		if (isMerged) {
			throw new IllegalStateException("Maps have already been merged");
		}
	}

	// map delegates (except hashCode and equals)

	public int size() {
		return getCachedMerge().size();
	}

	public void clear() {
		getCachedMerge().clear();
	}

	public boolean isEmpty() {
		return getCachedMerge().isEmpty();
	}

	public boolean containsKey(Object key) {
		return getCachedMerge().containsKey(key);
	}

	public boolean containsValue(Object value) {
		return getCachedMerge().containsValue(value);
	}

	public Collection values() {
		return getCachedMerge().values();
	}

	public void putAll(Map t) {
		getCachedMerge().putAll(t);
	}

	public Set entrySet() {
		return getCachedMerge().entrySet();
	}

	public Set keySet() {
		return getCachedMerge().keySet();
	}

	public Object get(Object key) {
		return getCachedMerge().get(key);
	}

	public Object remove(Object key) {
		return getCachedMerge().remove(key);
	}

	public Object put(Object key, Object value) {
		return getCachedMerge().put(key, value);
	}

}